from utils.http_utils import *
from utils.cv2_utils import get_image_from_url, concatenate_image_by_roi_coordinates, pillow_to_cv2, save_image_with_chinese_path
from PIL import Image
import os
import numpy as np
import cv2
from utils.config_utils import load_config

# 获取当前文件的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
config = load_config(os.path.join(current_dir, 'config.json'))
yj_cookie = config.get('cookie', '')

class StudentData:
    '''
    学生的数据，包括姓名、考号、图片、科目ID、题块数据、模板ID、学校ID、学校名称
    '''
    def __init__(self, student_name, student_kaohao, schoolid=None, school_name=None, subject_id=None, files=None, blocks=None, templateid=None, ):
        self.student_name = student_name
        self.student_kaohao = student_kaohao
        self.schoolid = schoolid
        self.school_name = school_name
        self.subject_id = subject_id
        self.files = files
        self.blocks = blocks
        self.templateid = templateid

    def set_school_info(self, schoolid, school_name):
        self.schoolid = schoolid
        self.school_name = school_name

    def set_subject_info(self, subject_id, files, blocks, templateid):
        self.subject_id = subject_id
        self.files = files
        self.blocks = blocks
        self.templateid = templateid

    def get_template_id(self):
        return self.templateid

    def get_school_info(self):
        return self.schoolid, self.school_name
    
    def get_student_info(self):
        return self.student_name, self.student_kaohao
    
    def get_image_file_keys(self):
        return self.files
    
    def get_block_score(self, blockid):
        for block in self.blocks:
            if block['id'] == blockid:
                return block['score']
        return -1

class BlockData:
    '''
    题块的数据，包括题块ID、分数、坐标、学生图片
    '''
    def __init__(self, blockid, score=None, block_pos=None, files=None, cookie = yj_cookie):
        self.block_img_api = 'http://gray-yj-api.haofenshu.com/v353/image/urls/scale'
        self.cookie = cookie
        self.blockid = blockid
        self.score = score
        self.block_pos = block_pos
        self.files = files

    def get_block_score(self):
        return self.score
    
    def get_block_images(self):
        try:
            # 自定义header参数
            headers = {
                'cookie': self.cookie  
            }

            # TODO: 这里先取题块的第一张图，对于有多个子图的题块后面再处理
            '''
            block_pos的结构如下：
            "block_pos": [
                [
                    0,
                    42,
                    1133,
                    1394,
                    469
                ]
            ]
            '''
            if len(self.block_pos) < 1:
                return None
            
            #print('block pos: ', self.block_pos)
            
            file_index, x, y, w, h = self.block_pos[0]
            file = self.files[file_index]

            params = {
                'images':[
                    {                
                    'file': file,
                    'x': x,
                    'y': y,
                    'w': w,
                    'h': h
                    }
                ]
            }

            block_image_list = []
            response = post_request(self.block_img_api, headers=headers, json=params)
            if response is None:  # 检查响应是否包含预期数据:
                return block_image_list
            
            response_data = response.json()       
            block_image_list = response_data.get('data', {})

        except requests.exceptions.RequestException as e:
            print(f"Error fetching data: {e}")
        
        return block_image_list        



class TemplateData:
    '''
    模板的数据，包括模板ID、模板名称、客观题信息、主观题信息、模板图片
    '''
    def __init__(self, templateid, template_name=None, obj_info=None, sub_info=None, kaohao_info=None):
        self.templateid = templateid
        self.template_name = template_name
        self.obj_info = obj_info
        self.sub_info = sub_info
        self.kaohao_info = kaohao_info

    def __init__(self, templateid, template):
        self.templateid = templateid
        self.template_name = template['name']
        #self.obj_info = template['obj_info']
        self.sub_info = template['sub_info']
        #self.kaohao_info = template['kaohao_info']

    # 根据主观题的题块ID获取坐标
    def get_sub_block_pos(self, block_id):
        for block in self.sub_info:
            if block['blockid'] == block_id:
                return block['block_pos']
        return None



class SubjectData:
    '''
    科目的打分数据、学校列表，学生列表，题块坐标，题块图片
    '''
    def __init__(self, subject_id, cookie = yj_cookie):
        self.subject_id = subject_id
        #self.block_id = block_id
        self.cookie = cookie
        self.score_api = 'https://gray-yj-api.haofenshu.com/v1/get/all/report'
        self.template_api = f'https://grayyue.haofenshu.com/filter/yue/v353/template/query?subjectId={self.subject_id}'
        self.imagekey_to_url_api = 'https://gray-yj-api.haofenshu.com/v353/image/urls'
        self.school_list = []
        self.student_kaohao_list = []
        self.block_coordinates = []


    # 从report里获取本科目的学校列表
    def fetch_school_list(self):
        try:
            # 自定义header参数
            headers = {
                'cookie': self.cookie  
            }

            params = {
                'subjectId': self.subject_id,
                "stuDetail":False
            }

            school_list = []
            response = post_request(self.score_api, headers=headers, json=params)
            if response is None:  # 检查响应是否包含预期数据:
                return school_list
            
            response_data = response.json()       
            data = response_data.get('data', {})
            school_data = data.get("[schools]", [])

            for school in school_data:
                school_id = school.get("id")
                if school_id and school_id not in school_list:
                    school_info = {'school_id': school_id, 'school_name': school.get('name')}
                    school_list.append(school_info)

        except requests.exceptions.RequestException as e:
            print(f"Error fetching data: {e}")
        
        return school_list

    # 从report里获取某个学校的所有学生某个题块的数据
    def fetch_block_data_of_all_students(self, schoolid):
        try:
            # 自定义header参数
            headers = {
                'cookie': self.cookie  
            }

            params = {
                'subjectId': self.subject_id,
                "schoolId":schoolid
            }

            student_list = []
            response = post_request(self.score_api, headers=headers, json=params)
            if response is None:  # 检查响应是否包含预期数据:
                return student_list
            
            response_data = response.json()
            data = response_data.get('data', {})
            school_data = data.get("[schools]", [])
            # 因为是按学校查询的，所以这里只有一个学校的数据
            if len(school_data) < 1:
                return student_list
            
            current_school = school_data[0]
            school_name = current_school.get('name', '')
            stus = current_school.get("[stus]", [])

            for stu in stus:
                image_files = stu.get('[files]', [])
                if len(image_files) < 1:
                    continue

                student_kaohao = stu.get('kaohao', '')
                student_name = stu.get('name', '')
                block_data = stu.get('[blocks]', [])
                if len(block_data) < 1:
                    continue
                templateid = stu.get('templateid', 0)

                # student_data = {
                #             'schoolid': schoolid, 
                #             'school_name': school_name,
                #             'subject_id':self.subject_id, 
                #             'student_kaohao': student_kaohao, 
                #             'files': image_files,
                #             'blocks': block_data,
                #             'name': student_name, 
                #             'templateid': templateid
                #         }
                student = StudentData(student_name, student_kaohao, schoolid, school_name, self.subject_id, image_files, block_data, templateid)
                student_list.append(student)

        except requests.exceptions.RequestException as e:
            print(f"Error fetching data: {e}")
        
        return student_list

    # 从report里获取某个学生的所有题块数据
    def fetch_student_data(self, kaohao):
        try:
            # 自定义header参数
            headers = {
                'cookie': self.cookie  
            }

            params = {
                'subjectId': self.subject_id,
                "kaohao":kaohao
            }

            response = post_request(self.score_api, headers=headers, json=params)
            if response is None:  # 检查响应是否包含预期数据:
                return None
            
            response_data = response.json()       
            data = response_data.get('data', {})
            #print('student data : ', data)

            student_data = dict()
            student_data['kaohao'] = kaohao
            student_data['files'] = data['[files]']
            student_data['blocks'] = data['[blocks]']
            student_data['name'] = data['name']
            student_data['templateid'] = data['templateid']
            student_data['schoolid'] = data['schoolId']

            return student_data

        except requests.exceptions.RequestException as e:
            print(f"Error fetching data: {e}")
        
        return None

    # 图片key转为可下载的url
    def transform_image_file_key_to_url(self, image_file):
        
        params = {
            'images': [image_file]
        }

        response = post_request(self.imagekey_to_url_api, json=params)
        if response is None:
            return None
        return response.json()['data']
    
    def get_templates(self):
        try:
            # 自定义header参数
            headers = {
                'cookie': self.cookie  
            }

            response = get_request(self.template_api, headers=headers)
            if response is None:  # 检查响应是否包含预期数据:
                return None
            
            response_data = response.json()       
            template_list = response_data.get('data', {})
            #print('template_list : ', template_list[0])
            
            return template_list

        except requests.exceptions.RequestException as e:
            print(f"Error fetching data: {e}")
        
        return None

    # 根据模板ID返回模板的数据
    def get_template_by_id(self, template_id):
        try:
            # 自定义header参数
            headers = {
                'cookie': self.cookie  
            }

            response = get_request(self.template_api, headers=headers)
            if response is None:  # 检查响应是否包含预期数据:
                return None
            
            response_data = response.json()       
            template_list = response_data.get('data', {})
            #print('student data : ', data)
            if len(template_list) < 1:
                return None
            
            # 模板ID是按顺序的，所以按顺序取就可以
            template = None
            if len(template_list) > template_id:
                template = template_list[template_id]
            else:
                template = template_list[0]
            
            return template

        except requests.exceptions.RequestException as e:
            print(f"Error fetching data: {e}")
        
        return None



# 从report里获取学生的批改分数信息
def fetch_student_data(subject_id, student_kaohao, cookie = yj_cookie):
    try:
        # 自定义header参数
        headers = {
            'cookie': cookie  # 假设你需要传递一个Bearer token
        }

        url = 'https://gray-yj-api.haofenshu.com/v1/get/all/report'

        params = {
            'subjectId': subject_id,
            'kaohao': student_kaohao
        }

        response = post_request(url, headers=headers, json=params)
        if response is None or 'data' not in response.json():  # 检查响应是否包含预期数据:
            return None
        
        score_data = response.json()['data']
        #print('score_data: ', score_data)
        if score_data is None or '[files]' not in score_data.keys() or 'kaohao' not in score_data.keys() or 'name' not in score_data.keys() or '[blocks]' not in score_data.keys():
            print("Error: Data format is different from expected.")
            return None

        # print('key: ', score_data.keys())

        # if '[files]' not in score_data.keys():
        #     print('test1')
        #     return None
        # if 'kaohao' not in score_data.keys():
        #     print('test2')
        #     return None        
        # if 'name' not in score_data.keys():
        #     print('test3')
        #     return None                
        # if '[blocks]' not in score_data.keys():
        #     print("Error: Data format is different from expected.")
        #     return None

        image_files = score_data['[files]'][-1]  # 默认最后一张有作文图
        student_kaohao = score_data['kaohao']
        student_name = score_data['name']
        essay_score = score_data['[blocks]'][-1]['score']
        templateid = score_data['templateid']
        essay_block_id = score_data['[blocks]'][-1]['id']

        result = {
                    'subject_id':subject_id, 
                    'student_kaohao': student_kaohao, 
                    'student_name': student_name, 
                    'essay_score': essay_score, 
                    'image_files': image_files, 
                    'templateid': templateid,
                    'essay_block_id':essay_block_id
                }
        
        return result
    except requests.exceptions.RequestException as e:
        print(f"Error fetching data: {e}")
        return None
    
# 从report里获取某个学校的所有学生作文数据（默认最后一个题块是作文）
def fetch_school_data(subject_id, school_id, cookie = yj_cookie):
    try:
        # 自定义header参数
        headers = {
            'cookie': cookie  
        }

        url = 'https://gray-yj-api.haofenshu.com/v1/get/all/report'

        params = {
            'subjectId': subject_id,
            "schoolId":school_id
        }

        students_data = []
        response = post_request(url, headers=headers, json=params)
        if response is None:  # 检查响应是否包含预期数据:
            return students_data
        
        response_data = response.json()       
        data = response_data.get('data', {})
        school_data = data.get("[schools]", [])

        if len(school_data) < 1:  # 应该有一个学校的数据
            return students_data
        
        current_school = school_data[0]
        school_name = current_school.get('name', '')

        #print(f"school_name : {school_name}, school_id : {school_id}")

        stus = current_school.get("[stus]", [])
        for stu in stus:
            image_files = stu.get('[files]', [])
            if len(image_files) < 1:
                continue
            image_file = image_files[-1]# 默认最后一张有作文图

            student_kaohao = stu.get('kaohao', '')
            student_name = stu.get('name', '')
            block_data = stu.get('[blocks]', [])
            if len(block_data) < 1:
                continue
            essay_score = block_data[-1]['score']
            templateid = stu.get('templateid', 0)

            student_data = {
                        'school_id': school_id, 
                        'school_name': school_name,
                        'subject_id':subject_id, 
                        'student_kaohao': student_kaohao, 
                        'student_name': student_name, 
                        'essay_score': essay_score, 
                        'image_files': image_file, 
                        'templateid': templateid
                    }
            students_data.append(student_data)

        return students_data
    except requests.exceptions.RequestException as e:
        print(f"Error fetching data: {e}")
        return students_data
            

    
# 从report里获取学校列表
def fetch_school_list(subject_id, cookie = yj_cookie):
    try:
        # 自定义header参数
        headers = {
            'cookie': cookie  
        }

        url = 'https://gray-yj-api.haofenshu.com/v1/get/all/report'

        params = {
            'subjectId': subject_id,
            "stuDetail":False
        }

        school_list = []
        response = post_request(url, headers=headers, json=params)
        if response is None:  # 检查响应是否包含预期数据:
            return school_list
        
        response_data = response.json()       
        data = response_data.get('data', {})
        school_data = data.get("[schools]", [])

        for school in school_data:
            school_id = school.get("id")
            if school_id and school_id not in school_list:
                school_info = {'school_id': school_id, 'school_name': school.get('name')}
                school_list.append(school_info)

    except requests.exceptions.RequestException as e:
        print(f"Error fetching data: {e}")
    
    return school_list

    
# 图片key转为可下载的url
def transform_image_file_to_url(image_file):
    
    url = 'https://gray-yj-api.haofenshu.com/v353/image/urls'

    params = {
        'images': [image_file]
    }

    response = post_request(url, json=params)
    if response is None:
        return None
    return response.json()['data']

# 从模板结构里获取作文的题块坐标，默认取最后一道主观题
def get_essay_coordinates(subject_id, template_index = 0, essay_block_id = None, cookie = yj_cookie):

    # 自定义header参数
    headers = {
        'cookie': cookie
    }

    url = f'https://grayyue.haofenshu.com/filter/yue/v353/template/query?subjectId={subject_id}'

    response = get_request(url, headers=headers)
    if response is None:
        return None
    templates = response.json()['data']
    if templates is None or len(templates) < 1:
        return None

    template = templates[template_index]
    #print('template : ', template['sub_info'])
    sub_info = template['sub_info']
    essay_blocks = []
    if essay_block_id is None:
        essay_blocks = sub_info[-1]['block_pos']
    else:
        for block in sub_info:
            if block['blockid'] == essay_block_id:
                essay_blocks = block['block_pos']
                break
    #essay_blocks = template['sub_info'][-1]['block_pos']

    boxs = []
    for block in essay_blocks:
        #print("block : ", block)
        _, x, y, w, h = block
        box = (x,y, w, h)
        boxs.append(box)

    print('boxs : ', boxs)    
    return boxs

# 获取考试的所有科目信息
def get_subject_list(exam_id, cookie = yj_cookie):

    try:
        # 自定义header参数
        headers = {
            'cookie': cookie  
        }

        url = 'https://gray-yj-api.haofenshu.com/v353/exam/info'

        params = {
            "examId": exam_id,
            "options":["papers"]
        }

        subject_list = []
        response = post_request(url, headers=headers, json=params)
        if response is None:  # 检查响应是否包含预期数据:
            return subject_list

        response_data = response.json()       
        subject_list = response_data.get('data', {})
    except requests.exceptions.RequestException as e:
        print(f"Error fetching data: {e}")
    
    return subject_list


# 获取某场考试的语文科目信息
def get_chinese_subject_info(exam_id, cookie = yj_cookie):
    subject_list = get_subject_list(exam_id, cookie)
    if subject_list is None or len(subject_list) < 1:
        return None
    
    grades = ['高一', '高二', '高三'] # 先只取高中学段的考试
    chinese_subject_info = None
    print('get_chinese_subject_info subject_list: ', subject_list)
    for subject in subject_list:
        if subject['subject'] == '语文':
            if subject['grade'] not in grades:
                break

            chinese_subject_info = {'exam_id':exam_id, 'subject_id': subject['id'], 'grade': subject['grade']}
            break
    return chinese_subject_info
    


def save_image_from_path(image_url, save_to_path=None):
    image = get_image_from_url(image_url)
    if image :
        image.save(save_to_path)


def generate_save_path(subject_id, student_kaohao, student_name, score):
    return f"{subject_id}_{student_kaohao}_{student_name}_{score}.png"


# 获取作文的图片url
def get_image_url(subject_id, kaohao):
    student_data = fetch_student_data(subject_id, kaohao)
    if student_data is None:
        return None
    image_url = transform_image_file_to_url(student_data['image_files'])
    if image_url is None or len(image_url) < 1:
        return None
    return image_url[0]


# 获取图片的整个流程
def get_image_pipeline(subject_id, kaohao):
    """
    获取图片的整个流程。
    
    参数：
    - subject_id: 科目ID
    - kaohao: 考号
    
    返回：
    - res: 是否成功（布尔值）
    - full_save_path: 保存图片的完整路径
    - image_url: 图片的URL
    """

    res = False
    full_save_path = None

    try:

        # 获取学生分数信息
        student_data = fetch_student_data(subject_id, kaohao)
        if student_data is None:
            return res, None, None
        
        # 转换图片key为url
        image_url = transform_image_file_to_url(student_data['image_files'])
        if image_url is None or len(image_url) < 1:
            return res, None, None
        
        # 获取作文题块坐标
        essay_coordinates = get_essay_coordinates(subject_id, student_data['templateid'], student_data['essay_block_id'])
        if essay_coordinates is None:
            return res, None, None
        
        # 下载图片并拼接
        image = get_image_from_url(image_url[0])
        #print("pillow to cv2")
        cv_image = pillow_to_cv2(image)  # 灰度图
        #print("pillow to cv2 done.")
        concatenate_image = concatenate_image_by_roi_coordinates(cv_image, essay_coordinates)
        # 保存图片
        if concatenate_image is not None:
            save_path = generate_save_path(subject_id, kaohao, student_data['student_name'], student_data['essay_score'])
            full_save_path = os.path.join('./data/', save_path)
            if os.path.exists(full_save_path):
                os.remove(full_save_path)
            save_image_with_chinese_path(concatenate_image, full_save_path)
            res = True

    except Exception as e:
        print(f"Error: {e}")

    return res, full_save_path, image_url[0]
    



if __name__ == "__main__":
    subject_id = 8849324
    #subject_id = 8708401
    kaohao = '0229201156'

    # get_essay_coordinates(subject_id, template_index=0)

    # 获取某个学生的数据
    res, _, img_url = get_image_pipeline(subject_id, kaohao)
    if res:
        print("Success! ", img_url)
    else:
        print("Failed!", img_url)

    # 获取某个科目下某个学校的所有学生的数据
    # subject_id = 8847372
    # # school_id = 28743
    # # school_data = fetch_school_data(subject_id, school_id)

    # # print(len(school_data), school_data[0])

    # school_list = fetch_school_list(subject_id)
    # print(len(school_list), school_list)


    # exam_id = 2236396
    # chinese_subject_info = get_chinese_subject_info(exam_id)
    # print('chinese_subject_info : ', chinese_subject_info)




    # data = fetch_student_data(subject_id, kaohao)
    # if data is not None:
    #     print(data)

    # image_file = data['image_files']
    # image_url = transform_image_file_to_url(image_file)
    # print('image_url : ', image_url)

    # save_path = generate_save_path(subject_id, kaohao, data['student_name'], data['essay_score'])
    # print(generate_save_path(subject_id, kaohao, data['student_name'], data['essay_score']))

    # save_image_from_path(image_url[0], os.path.join('../data/', save_path))



    
